home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
The World of Computer Software.iso
/
watchit1.zip
/
WATCHIT1.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-08-14
|
34KB
|
771 lines
page 80,132
;****************************************************************************
; WATCHCAT copyright 1989, Joseph R. Ahlgren
; see WATCHCAT.DOC
;****************************************************************************
; WATCHIT1 modification July 29, 1990 Cody Gibson - Added command line
; parameters to control the inactivity reset time, and the number of
; modem rings reset count.
;****************************************************************************
; WATCHIT1 performs 5 critical functions for any BBS system:
;
; 1. Reboots system if no carrier detected in specified period of time.
; This catches BBS or system failures.
;
; 2. Reboots system if carrier is lost during a "critical" period.
; This allows Doors to be used safely.
;
; 3. Reboots system if too many rings detected without answering phone.
; This allows the system to be restarted (rebooted) by phone.
;
; 4. Reboots system if "Hit any key to return to system" message appears.
; This restarts the system on a common RBBS failure.
;
; 5. Drops carrier if L&R shift keys pressed simultaneously.
; This allows users to be logged off without a nasty message.
;
; WATCHIT1 loads the TSR and disables all functions
; WATCHIT1 OFF disables all functions
; WATCHIT1 ON enables 1, 3, 4, and 5
; WATCHIT1 TIMER enables 2,4,and 5
;
;****************************************************************************
;****************************************************************************
LowMem Segment at 0040h ; BIOS data segment
Org 0
COM1_Port dw ? ; Location of the COM1 port address
Org 17h
ShiftStatus db ? ; Location of shift status within BIOS data segment
LowMem Ends
;****************************************************************************
.model small
.code
First Equ This Byte
;****************************************************************************
; Constants
;****************************************************************************
DOS Equ 21h ; DOS functions interrupt
Print Equ 09h ; DOS Print string function
Set_Vector Equ 25h ; DOS Set interrupt vector function
TSR Equ 31h ; DOS Terminate Stay Resident function
Get_Vector Equ 35h ; DOS Get interrupt vector function
;****************************************************************************
IfDef Debug
Timer_Vector Equ 61h ; For debugging only
else
Timer_Vector Equ 08h ; Vector number of the 18.2 ticks/second timer
Endif
ModemStatus Equ 06h ; Index to Modem Status port
ModemControl Equ 04h ; Index to Modem Control port
CarrierDetect Equ 80h ; Carrier Detect bit within status byte
RingIndicator Equ 40h ; Ring Indicator bit within modem status
TPM Equ 1092 ; Ticks/Minute = 18.2 * 60
RingTicks Equ 109 ; Time/phone ring = 6 seconds = 18.2 * 6
ComPort1 Equ 03F8h ; COM1 base address
ComPort2 Equ 02F8h ; COM2 base address
ComPort3 Equ 03E8h ; COM3 base address
ComPort4 Equ 02E8h ; COM4 base address
ComPort5 Equ 03D8h ; COM5 base address
ComPort6 Equ 02D8h ; COM6 base address
ComPort7 Equ 03C8h ; COM7 base address
ComPort8 Equ 02C8h ; COM8 base address
ColorScreen Equ 0B800h ; Color screen segment address
MonoScreen Equ 0B000h ; Mono screen segment address
DropTrigger Equ 3 ; Drop DTR on L&R shift
NL Equ <0Dh,0Ah> ; Newline definition
;****************************************************************************
;****************************************************************************
; The beginning of a .COM file begins at 100h
;****************************************************************************
Org 100h
Start: Jmp Init
;****************************************************************************
;****************************************************************************
Ringing db 0 ; Flag indicating line is ringing
RingLimit db 4 ; Number of rings required to reboot
; Default to 4 rings
RingCount db 0 ; Count of rings received
RingTimer db RingTicks ; Phone ring count down timer (set to 6 seconds)
Flag db 'F' and 0Fh ; OFF ON TIME = F N I
TimerInt dd ? ; Original timer interrupt vector
MinReset dw 6*60 ; Minutes of no carrier to trigger reset
; Default to 3 hours
Minutes dw ? ; Minutes left before rebooting
; Default to 3 hours
Seconds dw TPM ; 60 second counter
ColdBoot dd 0FFFF0000h ; Address to JMP to perform cold boot
ExitTimer db 0
ExitMessage db 'Hit any key to return to system'
ExitMessageSize Equ $ - ExitMessage
ComPort dw ComPort1 ; Comm port base address
; default to COM1
ScreenSegment dw MonoScreen ; Screen memory segment address
; default to mono
Ident db "Watchit1 V2.00, (C) 1990 by Joseph R. Ahlgren"
Ident_CRC dw 0
Signature_Size Equ $ - Ident ; Size of the signature string
PSPSeg dw 0 ; Our PSP segment address
;****************************************************************************
; This is the captured Timer Interrupt entry point
;****************************************************************************
Timer Proc Near
Assume DS:Nothing,ES:Nothing,SS:Nothing
Cmp CS:[Flag],'F' and 0Fh ; Have we been turned off?
Jne SystemOn ; no, Check system status
IfDef Debug
Iret ; Simply return in debugging mode
Else
Jmp CS:[TimerInt] ; yes, goto original vector
Endif
;****************************************************************************
; We are enabled, save registers and check system status
;****************************************************************************
SystemOn:
Push AX ; Save registers
Push DX ; "
Push DS ; "
Push ES ; "
;****************************************************************************
; 4. Reboots system if "Hit any key to return to system" message appears
; This restarts system on a common RBBS failure
;****************************************************************************
Dec CS:[ExitTimer] ; Only check condition 4 every 256
; timer ticks (every 14 seconds)
; Have we reached 256 ticks?
Jnz NoExitLoop ; no, Skip condition 4 check
;****************************************************************************
; yes, Scan screen for the message
Push CX ; Save registers
Push SI ; "
Push DI ; "
;****************************************************************************
Mov AX,CS:[ScreenSegment] ; Get segment address of the screen
Mov DS,AX ; Point to screen memory
Mov AX,CS ; Point to our own data segment
Mov ES,AX ; "
Mov CX,25 ; Scan 25 lines
Xor SI,SI ; Start at line 0
;****************************************************************************
SSLoop1:
Push CX ; Save current line count
Push SI ; Save current line address
Mov CX,ExitMessageSize ; Get size of the exit message
Lea DI,ExitMessage ; Point to the exit message to compare against
;****************************************************************************
Cld ; Auto-increment SI & DI
SSLoop2:
Cmpsb ; Is the exit message being displayed here?
Jne ExitNotFound ; no, Check the next line
Inc SI ; Skip the attribute byte
Loop SSLoop2
;****************************************************************************
Jmp Reboot ; yes, Reboot the computer!!!
;****************************************************************************
ExitNotFound:
Pop SI ; Restore line address
Pop CX ; Restore line count
Add SI,160 ; Point to the next line
Loop SSLoop1 ; Scan all 25 screen lines
;****************************************************************************
Pop DI ; Restore registers
Pop SI ; "
Pop CX ; "
;****************************************************************************
; 5. Drops carrier if L&R shift keys pressed simultaneously
; This allows users to be logged off without a nasty message.
;****************************************************************************
NoExitLoop:
Mov AX,Lowmem ; Get address of BIOS data
Mov DS,AX ; Point to BIOS data
Assume DS:Lowmem
Mov AL,[ShiftStatus] ; Get current shift state
And AL,0Fh ; Mask off shift state bits
Cmp AL,DropTrigger ; Is the proper shift state set?
Jne NoShift ; no, Check the next condition
;****************************************************************************
; yes, Drop the link by dropping DTR
Mov DX,CS:[ComPort] ; Get the Comm ports base address
Add DX,ModemControl ; Point to the modem control port
In AL,DX ; Get current state of control lines
And AL,0FEh ; Turn off the DTR line bit
Out DX,AL ; Drop DTR to the modem
;****************************************************************************
; 3. Reboots system if too many rings without answering phone
; This allows system to be restarted by phone
;****************************************************************************
NoShift:
Mov DX,CS:[ComPort] ; Get the Comm ports base address
Add DX,ModemStatus ; Point to the modem status port
In AL,DX ; Get the modems current status
Test AL,RingIndicator ; Is the line ringing?
Jz NoRing ; no, check how long it was ringing
;****************************************************************************
Or CS:[Ringing],1 ; yes, Set ringing indicator
;****************************************************************************
NoRing:
Dec CS:[RingTimer] ; Ring time expired (6 seconds)?
Jnz NoRingTime ; no, Check condition 2
Mov CS:[RingTimer],RingTicks ; yes, reset the ring timer
Test CS:[Ringing],1 ; Is the line ringing?
Jz NotRinging ; no, Reset triggers
Mov CS:[Ringing],0 ; Reset ringing indicator
Inc CS:[RingCount] ; Count the number of rings
Mov AL,CS:[RingCount] ; Get the ring count
Cmp AL,CS:[RingLimit] ; Have we reached the limit?
Jb NoRingTime ; no, Check condition 2
;****************************************************************************
Jmp Short Reboot ; yes, reboot machine
;****************************************************************************
NotRinging:
Mov CS:[RingCount],0 ; Ringing stopped, reset ring count
;****************************************************************************
; 2. Reboots system if carrier lost during "critical period"
; This allows Doors to be used safely
;****************************************************************************
NoRingTime:
Cmp CS:[Flag],'I' and 0Fh ; Is OFF flag on?
Jb NoMonitor ; yes, Exit and jump to original vector
; Is TIMER flag set?
Je TimeCheck ; yes,
In AL,DX ; no, ON is set, check for carrier loss
Test AL,CarrierDetect ; Is CD line set?
Jz Reboot ; no, Reboot machine
;****************************************************************************
NoMonitor:
Pop ES ; Restore registers
Pop DS ; "
Pop DX ; "
Pop AX ; "
IfDef Debug
Iret ; In debug mode, we're not actually
; attached to the timer interrupt
Else
Jmp CS:[TimerInt] ; Jump to original vector
Endif
;****************************************************************************
; Reboot the computer by jumping directly to the power on reset address
;****************************************************************************
Reboot:
Jmp CS:[ColdBoot] ; Reboot the computer
;****************************************************************************
; 1. Reboots system if no carrier in specified period of time
; This catches BBS or system failures
;****************************************************************************
TimeCheck:
Mov DX,CS:[ComPort] ; Get the Comm ports base address
Add DX,ModemStatus ; Point to the modem status port
In AL,DX ; Get the modems current status
Test AL,CarrierDetect ; Is CD line set?
Jnz ResetTime ; yes, Reset no carrier timer
;****************************************************************************
Dec CS:[Seconds] ; Have 60 seconds transpired?
Jnz NoMonitor ; no, Exit and jump to original vector
;****************************************************************************
Mov CS:[Seconds],TPM ; yes, Reset 60 second counter
Dec CS:[Minutes] ; Minutes count limit reached?
Jz Reboot ; yes, Reboot computer
;****************************************************************************
Jmp Short NoMonitor ; no, Exit and jump to original vector
;****************************************************************************
ResetTime:
Mov AX,CS:[MinReset] ; Get minutes count limit
Mov CS:[Minutes],AX ; Set count down timer
Mov CS:[Seconds],TPM ; Reset 60 second counter
Jmp Short NoMonitor ; Exit and jump to original vector
Timer Endp
;****************************************************************************
;****************************************************************************
; This is the actual start of the module. Control is passed to here upon
; loading of the program.
;****************************************************************************
;****************************************************************************
Assume DS:@Code,ES:@Code,SS:@Code
;****************************************************************************
Init Proc Near
Mov AX,CS ; Point DS to our segment
Mov DS,AX ; "
Mov CS:PSPSeg,ES ; Save address of our PSP
;****************************************************************************
Lea DX,SignOnMessage ; Print sign on message
Mov AH,Print ; "
Int DOS ; "
;****************************************************************************
; Scan memory to see if we're already loaded
;****************************************************************************
Xor DX,DX ; Start scanning at segment 0000
Mov ES,DX ; "
Mov BX,CS ; Make note of our segment
;****************************************************************************
Xor AX,AX ; Init CRC register
Lea SI,Ident ; Point to signature
Mov CX,Signature_Size ; Get length of signature
CRC: Shl AX,1 ; Compute next CRC value
Adc AX,0 ; Add the carry bit back in
Add AL,[SI] ; Add in this character into CRC
Adc AH,0 ; Add carry into high byte
Inc SI ; Point to next character
Loop CRC ; Loop for all characters
Mov Ident_CRC,AX ; Store computed CRC value
FindLoop:
Lea SI,Ident ; Point to signature
Mov DI,SI ; Copy the address of the signature
Mov CX,Signature_Size ; Get length of signature
Repz Cmpsb ; Does this segment contain the signature?
Jnz NotQuite ; no, check next segment
Jmp Found ; yes, found to be already loaded
;****************************************************************************
NotQuite:
Inc DX ; no, Examine next segment
Mov ES,DX ; Point to next segment
Cmp DX,BX ; Have we reached our own segment?
Jne FindLoop ; no, Continue scanning all memory segments
; yes, Stop scanning, go ahead and load
;****************************************************************************
; We're not already loaded. Parse the command line and then load as TSR.
;****************************************************************************
LoadWatchit1: ; Watchit1 not found. Go ahead and load as TSR
Push DS ; Save registers
;***************************************************************************
Push ES
Mov AX,Lowmem ; Point to BIOS data area
Mov ES,AX ; "
Assume ES:Lowmem
Mov AX,[COM1_Port] ; Pick up the COM1 port specification
; and use as the default
Mov CS:ComPort,AX ; Save the port address
Pop ES
Assume ES:@Code
;****************************************************************************
Mov DS,CS:PSPSeg ; Get our PSP
Mov SI,0080h ; Offset of command line
;***************************************************************************
Lodsb ; Get length of command line
Or AL,AL ; Check for zero
Jnz Cmd_Line_Data ; Information on command line
Jmp Cmd_Line_Exit ; Nothing on command line
;***************************************************************************
Cmd_Line_Data:
Xor CH,CH ; Set up count
Mov CL,AL ; "
;***************************************************************************
Cmd_Line_Loop:
Call Search_String ; Search for first option
Or AL,AL ; Check return code
Jz Cmd_Line_Entry ; Not string end
Jmp Cmd_Line_Exit ; End of string
;***************************************************************************
Cmd_Line_Entry:
Mov BX,DX ; Save count
Add BX,SI ; Adjust to next starting location
Lodsb ; Get first character
Dec DX ; Reduce string count
Jnz Cmd_Line_Code ; Option has data
Jmp Next_Cmd_Option ; Go to next string
;***************************************************************************
Cmd_Line_Code:
Cmp AL,'-' ; Check for option identifiers
Je Process_Option ; "
Cmp AL,'/' ; "
Je Process_Option ; String is valuid
Jmp Next_Cmd_Option ; Ignore string (not valid)
;***************************************************************************
Process_Option:
Lodsb ; Get next parameter
Dec DX ; Reduce count
And AL,0DFh ; Capitalize byte
;***************************************************************************
Cmp AL,'R' ; Is it the ring count parameter
Jne Not_RC ; no, Check next option
;***************************************************************************
Call Get_Cmd_Line_Dec ; Convert ASCII decimal number to hex
Mov CS:RingLimit,AL ; Set the ring limit count
Jmp Next_Cmd_Option ; Next option
;***************************************************************************
Not_RC: Cmp AL,'I' ; Is it the inactivity time parameter?
Jne Not_In ; no, Check next option
;***************************************************************************
Call Get_Cmd_Line_Dec ; Convert ASCII decimal number to hex
Mov CS:MinReset,AX ; Set number minutes to timeout
Jmp Short Next_Cmd_Option ; Next option
;***************************************************************************
Not_In: Cmp AL,'S' ; Is it the screen type indicator?
Jne Not_Sc ; no, Check next option
;***************************************************************************
Get_Scrn:
Lodsb ; Get next parameter
Dec DX ; Reduce count
;***************************************************************************
Cmp AL,':' ; Skip a ':' character
Jne Get_Scrn ; "
Cmp AL,'=' ; Skip a '=' character
Jne Get_Scrn ; "
;***************************************************************************
And AL,0DFh ; Capitalize byte
Cmp AL,'C' ; Is color specified?
Jne Not_Color ; no, Check for mono
Mov CS:ScreenSegment,ColorScreen ; Set color screen segment
Mov CS:ScreenSegNum,'8' ; Show B800 as screen segment
Jmp Short Next_Cmd_Option ; Next option
;***************************************************************************
Not_Color:
Cmp AL,'M' ; Is color specified?
Jne Not_Mono ; no, Check for mono
Mov CS:ScreenSegment,MonoScreen ; Set mono screen segment
Mov CS:ScreenSegNum,'0' ; Show B000 as screen segment
;***************************************************************************
Not_Mono:
Jmp Short Next_Cmd_Option ; Next option
;***************************************************************************
Not_Sc:
Cmp AL,'P' ; Is it the port parameter?
Jne Not_Port ; no, Check next option
;***************************************************************************
Call Get_Cmd_Line_Hex ; Convert ASCII decimal number to hex
Cmp AX,8 ; Values 1-8 mean COM1-COM8
Ja Port_Value ; Not a COM1-COM8 specification
;***************************************************************************
Mov CS:[ComPortNumber],AL ; Store the com specification
Add CS:[ComPortNumber],'0' ; Convert to ASCII
;***************************************************************************
Cmp AX,2 ; Values 1-2 can be read from BIOS
Ja Not_In_BIOS ; Greater the COM2 specified
Push ES
Mov BX,Lowmem ; Point to BIOS data area
Mov ES,BX ; "
Assume ES:Lowmem
Mov BX,AX ; Copy com number
Dec BX ; Convert to 0-1 range
Shl BX,1 ; Convert to word offset
Mov AX,ES:[BX] ; Pick up the com port specification
Mov CS:ComPort,AX ; Save the port address
Pop ES
Assume ES:@Code
;***************************************************************************
Port_Value:
Mov CS:ComPort,AX
Jmp Short Next_Cmd_Option ; Next option
;***************************************************************************
Not_In_BIOS:
Mov BX,AX ; Copy com port number
Dec BX ; Convert to 0-7 base
Shl BX,1 ; Convert from byte to word offset
Mov AX,CS:[ComPorts+BX] ; Get com port address for this number
Mov CS:ComPort,AX ; Save the port address
Jmp Short Next_Cmd_Option ; Next option
;***************************************************************************
Not_Port:
;***************************************************************************
Next_Cmd_Option:
Mov SI,BX ; set next starting location
JCXZ Cmd_Line_Exit ; no more options
Jmp Cmd_Line_Loop ; process next string
;***************************************************************************
Cmd_Line_Exit:
Pop DS ; restore register
;***************************************************************************
Mov AX,[MinReset] ; Preset the inactivity minutes counter
Mov [Minutes],AX ; "
;****************************************************************************
Mov AH,Get_Vector ; Get timer interrupt vector address
Mov AL,Timer_Vector ; "
Int DOS ; "
Mov [Word PTR TimerInt],BX ; Save current vector
Mov [Word PTR TimerInt+2],ES ; "
;****************************************************************************
Lea DX,Timer ; Point to new timer vector
Mov AH,Set_Vector ; Intercept timer interrupt vector
Mov AL,Timer_Vector ; Intercept timer interrupt vector
Int DOS ; "
;****************************************************************************
Lea DX,Message1 ; Display Loaded message
Mov AH,Print ; "
Int DOS ; "
;****************************************************************************
IfDef Debug
Infinite_Loop:
Int Timer_Vector ; In debugging mode, execute interrupt
Jmp Infinite_Loop ; forever to allow for debugging
Else
Mov DX,(Init-First+15)/16 ; Amount of memory to keep for TSR
Mov AH,TSR ; TSR
Mov AL,01h ; "
Int DOS ; "
Endif
;****************************************************************************
; WATCHIT1 already found to be resident. Modify the running flags per
; request.
;****************************************************************************
Found:
Mov AX,ES ; Copy segment value
Lea DI,Message2x ; Point to location to store ASCII conversion
Call Hex_To_Ascii ; Convert segment value to ASCII
;****************************************************************************
Mov AX,ES:[MinReset] ; Reset the inactivity timer
Mov ES:[Minutes],AX ; "
Mov AL,DS:[83h] ; Fetch second command line letter
And AL,0Fh ; Remove case sensitivity
Mov ES:[Flag],AL ; Save new setting
Lea DX,Message2tim ; Point to "TIMER" message
Cmp AL,'I' AND 0Fh ; Was TIMER set?
Jz Done ; yes, Display message and exit
Lea DX,Message2off ; Point to "OFF" message
; Was OFF set?
Jb Done ; yes, Display message and exit
Lea Dx,Message2on ; Point to "ON" message
Done:
Push DX ; Save pointer to TIMER/OFF/ON message
Lea DX,Message2 ; Display "FOUND" message
Mov AH,Print ; "
Int DOS ; "
Pop DX ; Restore pointer to TIMER/OFF/ON message
Mov AH,Print ; Display TIMER/OFF/ON message
Int DOS ; "
Mov AX,4C00h ; Return to DOS with no error code
Int DOS ; "
Hlt ; Should *NEVER* get to here!!!
Init Endp
;****************************************************************************
Message1 db NL,'WATCHIT1 Loaded, set to COM'
ComPortNumber db '1 and Screen B'
ScreenSegNum db '000.',NL,'$'
Message2 db 0Ah,0Dh,'WATCHIT1 found at '
Message2x db '0000 and set to $'
Message2on db 'ON.',NL,'$'
Message2off db 'OFF.',NL,'$'
Message2tim db 'TIMER.',NL,'$'
SignOnMessage db NL
db 'WATCHIT1 V1.00, Copyright 1990 Joseph R. Ahlgren',NL
db NL
db ' WATCHIT1 may be freely distributed provided this message is not modified',NL
db ' Load with WATCHIT1 [/R:NNN][/I:NNNNN][/S:C|M][/P:(1-8)|NNN]',NL
db ' where /R is the ring count from 1-255, /I is the Inactivity time limit',NL
db ' in minutes from 1-65535, /S is the screen to scan (C for Color, M for Mono)',NL
db ' and /P is the COM port to monitor (1-8 or any hex value). The default ring',NL
db ' count limit is 4, the default inactivity limit is 360 minutes (6 hours),',NL
db ' the default screen is Mono (B000), and the default COM port is COM1 (3F8).',NL
db NL
db ' Subsequent calls are WATCHIT1 ON, WATCHIT1 OFF, and WATCHIT1 TIMER.',NL
db ' OFF disables all functions.',NL
db ' ON reboots if carrier lost.',NL
db ' TIMER reboots if too many rings without answering phone, if no carrier',NL
db ' in hours, or if "Hit any key to return to system" appears on screen.',NL
db ' Also, pressing both Left and Right Shift keys simultaneously will',NL
db ' drop the line, logging off the current user.',NL
db NL
db '$'
;****************************************************************************
ComPorts dw ComPort1, ComPort2, ComPort3, ComPort4
dw ComPort5, ComPort6, ComPort7, ComPort8
;****************************************************************************
; Hex_To_Ascii: This routine will convert a binary number to an ASCII
; hexidecimal display, and store the characters in memory.
;
; Inputs: AX - Binary number to be converted
; DS:DI - Address to store the converted characters at
;
; Outputs: An ASCII string at DS:DI which can be printed to show the value
; of the binary number.
;****************************************************************************
Hex_To_Ascii Proc Near
Push BX ; Save registers
Push CX ; "
Push DI ; "
;****************************************************************************
Mov BX,10h ; Converting to Ascii Hex display
Mov CX,4 ; Number of digits to be converted
;****************************************************************************
Next_Digit:
Mul BX ; Push next nybble into DL
Cmp DL,9 ; Is this digit a number?
Jbe Number ; yes, Convert it to ASCII
;****************************************************************************
Add DL,'A' - '9' ; no, Add the constant to make it a letter
;****************************************************************************
Number:
Add DL,'0' ; Add the constant to make it ASCII
Mov [DI],DL ; Store the ASCII character
Inc DI ; Point to the next character location
Loop Next_Digit ; Loop for all digits
;****************************************************************************
Pop DI ; Restore registers
Pop CX ; "
Pop BX ; "
Ret ; Return to caller
Hex_To_Ascii Endp
;***************************************************************************
; This routine will search for the first parameter string:
; Input:
; DS:[SI] -- points to the data area to be searched
; CX -- number of bytes to search
; Output:
; AL -- return code: 00h - parameter
; 01h - not found
; 02h - terminate on Null (x'00')
; 03h - invalid length
; DS:[SI] -- points to the string found
; CX -- length left
; DX -- contains length of string
;***************************************************************************
Search_String Proc Near
Or CX,CX ; check length
Jnz SSLoop ; start search
Mov AL,03h ; set error code
Ret ; return to caller
;***************************************************************************
SSLoop:
Lodsb ; get a byte
Or AL,AL ; test for zero (Null)
Jz NullEnd ; end of string
Cmp AL,20h ; check for blank
Jne NonBlank ; Non-Blank character
Loop SSLoop ; try next character
;***************************************************************************
EndStr:
Mov AL,01h ; set return code
Ret ; return to caller
;***************************************************************************
NullEnd:
Mov AL,02h ; set return code
Ret ; return to caller
;***************************************************************************
NonBlank:
Push SI ; save index pointer
Mov DX,0001h ; set count register
SSLoopA:
Lodsb ; get a byte
Or AL,AL ; test for zero (Null)
Jz NonBEnd ; end of string
Cmp AL,0Dh ; check for CR
Jz NonBEnd ; end of string
Cmp AL,' ' ; check for blank
Jz NonBEnd ; end of string
Cmp AL,'/' ; check for slash
Jz NonBEnd ; end of string
Cmp AL,'-' ; check for hyphen
Je NonBEnd ; Non-Blank character
Inc DX ; one more
Loop SSLoopA ; try next character
Dec DX ; back up count one
;***************************************************************************
NonBEnd:
Pop SI ; restore index
Dec SI ; put si back one
Xor AL,AL ; zero out return code
Ret ; return to caller
Search_String Endp
;***************************************************************************
; Get_Cmd_Line_Hex -- This routine will convert an ASCII Hex string
; to a Hexidecimal value in AX.
; Input: DS:[SI] -- points to the ASCII Hex string
; DX -- # of bytes in string
; Output: AX -- Hex value
; DS:[SI] -- points to first byte after ASCII Hex string
;***************************************************************************
Get_Cmd_Line_Hex Proc Near
Push BX ; Save registers
Push CX ; "
Push DX ; "
Xor BX,BX ; Clear temporary results
Mov CL,04h ; Shift count
;***************************************************************************
Cmp DX,5 ; Maximum # of bytes to process
Jbe Cmd_Line_Number_Loop ; Number of char's is valid
Mov DX,5 ; Set maximum number (including a '='
; character)
;***************************************************************************
Cmd_Line_Number_Loop:
Or DX,DX ; Any characters left?
Jz Cmd_Line_Number_Exit ; No, exit routine
Xor AH,AH ; Clear high value of work register
Lodsb ; Get an ASCII digit
Dec DX ; Decrement character count
;***************************************************************************
Cmp AL,'=' ; Is it simply an '=' character?
Je Cmd_Line_Number_Loop ; yes, Just skip it
Cmp AL,':' ; no, Is it simply an ':' character?
Je Cmd_Line_Number_Loop ; yes, Just skip it
;***************************************************************************
Shl BX,CL ; Move hex digit to the left
And AL,0DFh ; no, Capitalize the character
Cmp AL,'9' ; Is this a character?
Jbe Hex_char_OK ; no, Skip adjustment
Sub AL,07h ; Adjust value
;***************************************************************************
Hex_char_OK:
And AL,0Fh ; Save hex number
Or BX,AX ; "
Jmp Cmd_Line_Number_Loop ; "
;***************************************************************************
Cmd_Line_Number_Exit:
Mov AX,BX ; Set return value
Pop DX ; Restore registers
Pop CX ; "
Pop BX ; "
Ret ; Return to caller
Get_Cmd_Line_Hex Endp
;***************************************************************************
; Get_Cmd_Line_Dec -- This routine will convert an ASCII decimal string
; to a Hexidecimal value in AX.
;
; Input: DS:[SI] -- points to the ASCII decimal string
; DX -- # of bytes in string
;
; Output: AX -- Hex value
; DS:[SI] -- points to first byte after ASCII Hex string
;***************************************************************************
Get_Cmd_Line_Dec Proc Near
Push BX ; Save registers
Push CX ; "
Push DX ; "
Xor BX,BX ; Clear temporary results
Mov CL,10 ; Multiplication factor for next digit
;***************************************************************************
Cmp DX,6 ; Maximum # of bytes to process
Jbe Dec_Number_Loop ; Number of char's is valid
Mov DX,6 ; Set maximum number (including a '='
; character)
;***************************************************************************
Dec_Number_Loop:
Or DX,DX ; Any characters left?
Jz Dec_Number_Exit ; No, exit routine
;***************************************************************************
Xor AH,AH ; Clear high value of work register
Lodsb ; Get an ASCII digit
Dec DX ; Decrement character count
;***************************************************************************
Cmp AL,'=' ; Is it simply an '=' character?
Je Dec_Number_Loop ; yes, Just skip it
Cmp AL,':' ; no, Is it simply an ':' character?
Je Dec_Number_Loop ; yes, Just skip it
;***************************************************************************
Xchg AX,BX ; Put value in AX for MUL
Mul CL ; Move digits to the left
Xchg BX,AX ; Save shifted value
And AL,0Fh ; Save decimal number
Add BX,AX ; "
Jmp Dec_Number_Loop ; "
;***************************************************************************
Dec_Number_Exit:
Mov AX,BX ; Set return value
Pop DX ; Restore registers
Pop CX ; "
Pop BX ; "
Ret ; Return to caller
Get_Cmd_Line_Dec Endp
End Start